﻿using System;
using System.Collections.Generic;
using Benchmark.Data;
using BenchmarkDotNet.Running;
using RepositoryModule;

namespace Benchmark;

internal class Program
{
    private static void Main(string[] args)
    {
        //Seed();

        //var result = BenchmarkRunner.Run<IncludeBenchmark>();
        //Console.ReadLine();

        //var result = BenchmarkRunner.Run<WhereBenchmark>();
        //Console.ReadLine();

        //using (var context = new BloggingContext())
        //{
        //    context.Database.EnsureDeleted();
        //    context.Database.EnsureCreated();
        //}

        //#region SingleInclude
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ToList();
        //}
        //#endregion

        //#region IgnoredInclude
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .Select(
        //            blog => new { Id = blog.BlogId, blog.Url })
        //        .ToList();
        //}
        //#endregion

        //#region MultipleIncludes
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .Include(blog => blog.Owner)
        //        .ToList();
        //}
        //#endregion

        //#region SingleThenInclude
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Author)
        //        .ToList();
        //}
        //#endregion

        //#region MultipleThenIncludes
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Author)
        //        .ThenInclude(author => author.Photo)
        //        .ToList();
        //}
        //#endregion

        //#region IncludeTree
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Author)
        //        .ThenInclude(author => author.Photo)
        //        .Include(blog => blog.Owner)
        //        .ThenInclude(owner => owner.Photo)
        //        .ToList();
        //}
        //#endregion

        //#region MultipleLeafIncludes
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Author)
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Tags)
        //        .ToList();
        //}
        //#endregion

        //#region IncludeMultipleNavigationsWithSingleInclude
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Owner.AuthoredPosts)
        //        .ThenInclude(post => post.Blog.Owner.Photo)
        //        .ToList();
        //}
        //#endregion

        //#region AsSplitQuery
        //using (var context = new BloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .AsSplitQuery()
        //        .ToList();
        //}
        //#endregion

        //using (var context = new SplitQueriesBloggingContext())
        //{
        //    context.Database.EnsureDeleted();
        //    context.Database.EnsureCreated();
        //}

        //#region WithSplitQueryAsDefault
        //using (var context = new SplitQueriesBloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .ToList();
        //}
        //#endregion

        //#region AsSingleQuery
        //using (var context = new SplitQueriesBloggingContext())
        //{
        //    var blogs = context.Blogs
        //        .Include(blog => blog.Posts)
        //        .AsSingleQuery()
        //        .ToList();
        //}
        //#endregion

        //#region Explicit
        //using (var context = new BloggingContext())
        //{
        //    var blog = context.Blogs
        //        .Single(b => b.BlogId == 1);

        //    context.Entry(blog)
        //        .Collection(b => b.Posts)
        //        .Load();

        //    context.Entry(blog)
        //        .Reference(b => b.Owner)
        //        .Load();
        //}
        //#endregion

        //#region NavQueryAggregate
        //using (var context = new BloggingContext())
        //{
        //    var blog = context.Blogs
        //        .Single(b => b.BlogId == 1);

        //    var postCount = context.Entry(blog)
        //        .Collection(b => b.Posts)
        //        .Query()
        //        .Count();
        //}
        //#endregion

        //#region NavQueryFiltered
        //using (var context = new BloggingContext())
        //{
        //    var blog = context.Blogs
        //        .Single(b => b.BlogId == 1);

        //    var goodPosts = context.Entry(blog)
        //        .Collection(b => b.Posts)
        //        .Query()
        //        .Where(p => p.Rating > 3)
        //        .ToList();
        //}
        //#endregion

        //#region FilteredInclude
        //using (var context = new BloggingContext())
        //{
        //    var filteredBlogs = context.Blogs
        //        .Include(
        //            blog => blog.Posts
        //                .Where(post => post.BlogId == 1)
        //                .OrderByDescending(post => post.Title)
        //                .Take(5))
        //        .ToList();
        //}
        //#endregion

        //#region MultipleLeafIncludesFiltered1
        //using (var context = new BloggingContext())
        //{
        //    var filteredBlogs = context.Blogs
        //        .Include(blog => blog.Posts.Where(post => post.BlogId == 1))
        //        .ThenInclude(post => post.Author)
        //        .Include(blog => blog.Posts)
        //        .ThenInclude(post => post.Tags.OrderBy(postTag => postTag.TagId).Skip(3))
        //        .ToList();
        //}
        //#endregion

        //#region MultipleLeafIncludesFiltered2
        //using (var context = new BloggingContext())
        //{
        //    var filteredBlogs = context.Blogs
        //        .Include(blog => blog.Posts.Where(post => post.BlogId == 1))
        //        .ThenInclude(post => post.Author)
        //        .Include(blog => blog.Posts.Where(post => post.BlogId == 1))
        //        .ThenInclude(post => post.Tags.OrderBy(postTag => postTag.TagId).Skip(3))
        //        .ToList();
        //}
        //#endregion

        //#region AutoIncludes
        //using (var context = new BloggingContext())
        //{
        //    var themes = context.Themes.ToList();
        //}

        //#endregion

        //#region IgnoreAutoIncludes
        //using (var context = new BloggingContext())
        //{
        //    var themes = context.Themes.IgnoreAutoIncludes().ToList();
        //}

        //#endregion
    }

    private static void Seed()
    {
        using (var context = new BloggingContext())
        {
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var random = new Random();

            var blogs = new List<Blog>();
            var posts = new List<Post>();
            var postTags = new List<PostTag>();
            var tags = new List<Tag>();

            for (int i = 1; i <= 50000; i++)
            {
                blogs.Add(new Blog()
                {
                    BlogId = i,
                    Url = @"https://devblogs.microsoft.com/dotnet",
                    Rating = 5,
                    OwnerId = 1,
                    ThemeId = 1
                });
            }

            for (int i = 1; i <= 100000; i++)
            {
                posts.Add(new Post()
                {
                    PostId = i,
                    BlogId = random.Next(1, 50000),
                    Title = "What's new",
                    Content = "Lorem ipsum dolor sit amet",
                    Rating = 5,
                    AuthorId = 1
                });
            }

            for (int i = 1; i <= 1000; i++)
            {
                tags.Add(new Tag()
                {
                    TagId = i.ToString(),
                });
            }

            int postTagId = 1;
            foreach (var post in posts)
            {
                var tag1 = random.Next(1, 100).ToString();
                var tag2 = random.Next(200, 400).ToString();
                var tag3 = random.Next(600, 800).ToString();
                var tag4 = random.Next(800, 1000).ToString();

                postTags.Add(new PostTag()
                {
                    PostTagId = postTagId++,
                    PostId = post.PostId,
                    TagId = tag1,
                });

                postTags.Add(new PostTag()
                {
                    PostTagId = postTagId++,
                    PostId = post.PostId,
                    TagId = tag2,
                });

                postTags.Add(new PostTag()
                {
                    PostTagId = postTagId++,
                    PostId = post.PostId,
                    TagId = tag3,
                });

                postTags.Add(new PostTag()
                {
                    PostTagId = postTagId++,
                    PostId = post.PostId,
                    TagId = tag4,
                });
            }

            context.Blogs.AddRange(blogs);
            context.Posts.AddRange(posts);
            context.Tags.AddRange(tags);
            context.PostTags.AddRange(postTags);
            context.SaveChanges();
        }
    }
}